package com.vshop.auth.strategy;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.vshop.auth.api.ApiUserService;
import com.vshop.auth.api.domain.dto.ApiLoginUser;
import com.vshop.auth.api.domain.vo.ApiClientVo;
import com.vshop.auth.domain.form.PasswordLoginBody;
import com.vshop.auth.domain.vo.AuthTokenVo;
import com.vshop.framework.core.domain.model.LoginUser;
import com.vshop.framework.core.util.MapstructUtil;
import com.vshop.framework.core.util.validate.ValidatorBeanUtil;
import com.vshop.framework.jackson.util.JsonUtil;
import com.vshop.framework.satoken.helper.LoginHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 密码认证策略
 */
@Slf4j
@Service("password" + AuthStrategy.BASE_NAME)
@RequiredArgsConstructor
public class PasswordAuthStrategy implements AuthStrategy {

    private final ApiUserService apiUserService;

    @Override
    public AuthTokenVo login(String body, ApiClientVo client) {
        PasswordLoginBody loginBody = JsonUtil.parseObject(body, PasswordLoginBody.class);
        ValidatorBeanUtil.validate(loginBody);

        String tenantId = loginBody.getTenantId();
        String username = loginBody.getUsername();
        String password = loginBody.getPassword();
        String code = loginBody.getCode();
        String uuid = loginBody.getUuid();

        // 此处可根据登录用户的数据不同 自行创建 loginUser
        ApiLoginUser apiLoginUser = apiUserService.getUserInfo(username);
        log.info("构建出 ApiLoginUser: {}", apiLoginUser);
        apiLoginUser.setClientKey(client.getClientKey());
        apiLoginUser.setDeviceType(client.getDeviceType());

        // 设置登录模型
        SaLoginModel model = new SaLoginModel();
        // 登录设备类型
        model.setDevice(client.getDeviceType());
        // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
        // 例如: 后台用户30分钟过期 app用户1天过期
        model.setTimeout(client.getTimeout());
        model.setActiveTimeout(client.getActiveTimeout());
        // 设置jwt额外数据
        model.setExtra(LoginHelper.ClientIdKey, client.getClientId());

        // 执行登录,生成token
        LoginUser loginUser = MapstructUtil.convert(apiLoginUser, LoginUser.class);
        LoginHelper.login(loginUser, model);

        AuthTokenVo authTokenVo = new AuthTokenVo();
        authTokenVo.setAccessToken(StpUtil.getTokenValue());
        authTokenVo.setExpireIn(StpUtil.getTokenTimeout());
        authTokenVo.setClientId(client.getClientId());
        return authTokenVo;
    }
}
